#ifndef _EXCEPTION_H
#define _EXCEPTION_H

#include "Object.h"

namespace demolib
{

#define EXCEPTION(e, message)  e(message, __FILE__, __LINE__)
#define THROW_EXCEPTION(e, m)   throw e(m, __FILE__, __LINE__)

class Exception : public Object
{
protected:
    char* m_message;    //异常信息
    char* m_location;   //抛出异常地址（文件名：行号）
    
    //异常信息处理函数，拼接文件名和行号
    void init(const char* message, const char* file, int line);
public:
    Exception(const char* message);
    Exception(const char* file, int line);
    Exception(const char* message, const char* file, int line);

    Exception(const Exception& e);
    Exception& operator= (const Exception& e);

    virtual const char* message()const;
    virtual const char* location()const;

    virtual ~Exception() = 0;
};

//计算异常类
class ArithmeticException : public Exception
{
public:
    ArithmeticException() : Exception(nullptr){ }
    ArithmeticException(const char* message) : Exception(message){ }
    ArithmeticException(const char* file, int line) : Exception(file, line){ }
    ArithmeticException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    ArithmeticException(const ArithmeticException& e) : Exception(e){ }
    ArithmeticException& operator=(const ArithmeticException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

//空指针异常类
class NullPointerException : public Exception
{
public:
    NullPointerException() : Exception(nullptr){ }
    NullPointerException(const char* message) : Exception(message){ }
    NullPointerException(const char* file, int line) : Exception(file, line){ }
    NullPointerException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    NullPointerException(const NullPointerException& e) : Exception(e){ }
    NullPointerException& operator=(const NullPointerException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

//越界异常类
class IndexOutOfBoundsException : public Exception
{
public:
    IndexOutOfBoundsException() : Exception(nullptr){ }
    IndexOutOfBoundsException(const char* message) : Exception(message){ }
    IndexOutOfBoundsException(const char* file, int line) : Exception(file, line){ }
    IndexOutOfBoundsException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    IndexOutOfBoundsException(const IndexOutOfBoundsException& e) : Exception(e){ }
    IndexOutOfBoundsException& operator=(const IndexOutOfBoundsException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

//内存不足异常类
class NoEnoughMemoryException : public Exception
{
public:
    NoEnoughMemoryException() : Exception(nullptr){ }
    NoEnoughMemoryException(const char* message) : Exception(message){ }
    NoEnoughMemoryException(const char* file, int line) : Exception(file, line){ }
    NoEnoughMemoryException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    NoEnoughMemoryException(const NoEnoughMemoryException& e) : Exception(e){ }
    NoEnoughMemoryException& operator=(const NoEnoughMemoryException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

//参数错误异常类
class InvalidParameterException : public Exception
{
public:
    InvalidParameterException() : Exception(nullptr){ }
    InvalidParameterException(const char* message) : Exception(message){ }
    InvalidParameterException(const char* file, int line) : Exception(file, line){ }
    InvalidParameterException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    InvalidParameterException(const InvalidParameterException& e) : Exception(e){ }
    InvalidParameterException& operator=(const InvalidParameterException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

//成员调用异常类
class InvalidOperationException : public Exception
{
public:
    InvalidOperationException() : Exception(nullptr){ }
    InvalidOperationException(const char* message) : Exception(message){ }
    InvalidOperationException(const char* file, int line) : Exception(file, line){ }
    InvalidOperationException(const char* message, const char* file, int line) : Exception(message, file, line){ }

    InvalidOperationException(const InvalidOperationException& e) : Exception(e){ }
    InvalidOperationException& operator=(const InvalidOperationException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

}

#endif //_EXCEPTION_H